package thread.communicate.tradition.communication;

import thread.unsafeExample.SafeAccount;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;

/**思路：
 *要同步互斥的几段代码最好是分别放在几个独立的方法中，这些方法再放在同一个类中，
 * 这样可以利用 this 作为同一个锁，比较容易实现它们之间的同步互斥和通信。
 *
 * 一下几种方法的不同点：
 * 同步代码块的位置不同，Runnable对象 的规划不同
 *
 * 如果每个线程执行的代码不同，这时候需要用不同的Runnable对象，有3种方式来实现这些Runnable对象之间的数据共享：
 * Method C:
 * 将这些Runnable对象作为某一个类中的内部类，共享数据作为这个外部类中的成员变量，
 * 每个线程对共享数据的操作方法放在共享对象身上，以便实现对共享数据进行的各个操作的互斥和通信，
 * 同步和互斥 的规则放在共享对象SafeAccount身上.
 * 作为内部类的各个Runnable对象调用共享对象身上的这些方法，以进行线程间的通讯。
 *
 * Created by 4790K_NSL on 2017/4/19.
 */
public class DiffRunnableCommunicationC {
    //共享数据
    private SafeAccount safeAccount =null;
    private double drawMoney;
    private double saveMoney;

    public DiffRunnableCommunicationC(SafeAccount safeAccount, double drawMoney, double saveMoney) {
        this.safeAccount = safeAccount;
        this.drawMoney = drawMoney;
        this.saveMoney=saveMoney;
    }

    public  boolean judge(){
        if(safeAccount.getAmount()>=0)
            return true;
        return false;
    }

    public void drawFromAccount(){
            safeAccount.draw(drawMoney);
    }

    public void saveToAccount(){

            safeAccount.save(saveMoney);

    }

    public void demo(){
        RunableA runnableA=new RunableA();
        RunableA runnableA1=new RunableA();
        RunableB runnableB=new RunableB();


        new Thread(runnableB).start();
        new Thread(runnableA).start();
        new Thread(runnableA1).start();

    }

    public static void main(String[] args) throws FileNotFoundException {
        final SafeAccount unsafeAccount=new SafeAccount(1,100);
        final double saveMoney=40;
        final double drawMoney=20;
        final boolean[] flag={true};
        PrintStream ps=new PrintStream(new FileOutputStream("d:/output.txt"));
        System.setOut(ps);
        DiffRunnableCommunicationC diffRunnableCommunicationB=new DiffRunnableCommunicationC(unsafeAccount,drawMoney,saveMoney);
        diffRunnableCommunicationB.demo();
    }



    class RunableA implements Runnable {

        @Override
        public void run() {
            while(judge()) {
                drawFromAccount();
            }
        }
    }

    class RunableB implements Runnable {

        @Override
        public void run() {
            while(judge()) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                saveToAccount();
            }
        }
    }


}

